/*
 * Copyright 2005-2013 yaojingmao.com. All rights reserved.
 * Support: http://www.yaojingmao.com
 * License: http://www.yaojingmao.com/license
 */
package net.shopxx.service.impl;

import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;

import javax.annotation.Resource;
import javax.servlet.ServletContext;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.log4j.Logger;
import org.springframework.core.task.TaskExecutor;
import org.springframework.stereotype.Service;
import org.springframework.web.context.ServletContextAware;
import org.springframework.web.multipart.MultipartFile;

import net.shopxx.Setting;
import net.shopxx.entity.ProductImage;
import net.shopxx.plugin.StoragePlugin;
import net.shopxx.service.ProductImageService;
import net.shopxx.util.FreemarkerUtils;
import net.shopxx.util.ImageUtils;
import net.shopxx.util.SettingUtils;

/**
 * Service - 商品图片
 * 
 * @author frankie
 * @version 3.0
 */
@Service("productImageServiceImpl")
public class ProductImageServiceImpl implements ProductImageService, ServletContextAware {

	/** logger */
	private static final Logger logger = Logger.getLogger(ProductImageServiceImpl.class);
	/** 目标扩展名 */
	private static final String DEST_EXTENSION = "jpg";
	/** 目标文件类型 */
	private static final String DEST_CONTENT_TYPE = "image/jpeg";

	/** servletContext */
	private ServletContext servletContext;

	@Resource(name = "taskExecutor")
	private TaskExecutor taskExecutor;
	@Resource
	private List<StoragePlugin> storagePlugins;

	public void setServletContext(ServletContext servletContext) {
		this.servletContext = servletContext;
	}

	/**
	 * 添加图片处理任务
	 * 
	 * @param sourcePath
	 *            原图片上传路径
	 * @param largePath
	 *            图片文件(大)上传路径
	 * @param mediumPath
	 *            图片文件(小)上传路径
	 * @param thumbnailPath
	 *            图片文件(缩略)上传路径
	 * @param tempFile
	 *            原临时文件
	 * @param contentType
	 *            原文件类型
	 */
	private void addTask(final String sourcePath, final String largePath, final String mediumPath, final String thumbnailPath, final File tempFile,
			final String contentType) {

		int count = 0;
		for (StoragePlugin storagePlugin : storagePlugins) {
			if (storagePlugin.getIsEnabled()) {
				count++;
			}
		}
		final CountDownLatch latch = new CountDownLatch(count);

		Collections.sort(storagePlugins);
		for (final StoragePlugin storagePlugin : storagePlugins) {
			if (storagePlugin.getIsEnabled()) {
				taskExecutor.execute(new Runnable() {
					public void run() {
						Setting setting = SettingUtils.get();
						String tempPath = System.getProperty("java.io.tmpdir");
						File watermarkFile = new File(servletContext.getRealPath(setting.getWatermarkImage()));
						File largeTempFile = new File(tempPath + "/upload_l" + UUID.randomUUID() + "." + DEST_EXTENSION);
						File mediumTempFile = new File(tempPath + "/upload_m" + UUID.randomUUID() + "." + DEST_EXTENSION);
						File thumbnailTempFile = new File(tempPath + "/upload_s" + UUID.randomUUID() + "." + DEST_EXTENSION);
						try {
							ImageUtils.zoom(tempFile, largeTempFile, setting.getLargeProductImageWidth(), setting.getLargeProductImageHeight());
							ImageUtils.addWatermark(largeTempFile, largeTempFile, watermarkFile, setting.getWatermarkPosition(), setting.getWatermarkAlpha());
							ImageUtils.zoom(tempFile, mediumTempFile, setting.getMediumProductImageWidth(), setting.getMediumProductImageHeight());
							ImageUtils.addWatermark(mediumTempFile, mediumTempFile, watermarkFile, setting.getWatermarkPosition(), setting.getWatermarkAlpha());
							ImageUtils.zoom(tempFile, thumbnailTempFile, setting.getThumbnailProductImageWidth(), setting.getThumbnailProductImageHeight());
							storagePlugin.upload(sourcePath, tempFile, contentType);
							storagePlugin.upload(largePath, largeTempFile, DEST_CONTENT_TYPE);
							storagePlugin.upload(mediumPath, mediumTempFile, DEST_CONTENT_TYPE);
							storagePlugin.upload(thumbnailPath, thumbnailTempFile, DEST_CONTENT_TYPE);

						} catch (Exception e) {
							logger.error("图片上传错误：" + e);
						} finally {
							FileUtils.deleteQuietly(largeTempFile);
							FileUtils.deleteQuietly(mediumTempFile);
							FileUtils.deleteQuietly(thumbnailTempFile);
							latch.countDown();
						}
					}
				});
			}
		}
		try {
			latch.await();
		} catch (InterruptedException e) {
			logger.error("临时图片删除错误：" + e);
		}
		FileUtils.deleteQuietly(tempFile);
	}

	public void build(ProductImage productImage) {
		MultipartFile multipartFile = productImage.getMultipartFile();
		File file = productImage.getFile();
		Boolean isCollected = productImage.isCollected();
		String fileName = null;
		String contentType = null;
		if (multipartFile != null && !multipartFile.isEmpty()) {
			fileName = multipartFile.getOriginalFilename();
			contentType = multipartFile.getContentType();
		} else if (isCollected) {
			fileName = file.getName();
			contentType = "application/octet-stream";
		}else{
			return;
		}
		
		try {
			Setting setting = SettingUtils.get();
			Map<String, Object> model = new HashMap<String, Object>();
			model.put("uuid", UUID.randomUUID().toString());
			String uploadPath = FreemarkerUtils.process(setting.getImageUploadPath(), model);
			String uuid = UUID.randomUUID().toString();
			String sourcePath = uploadPath + uuid + "-source." + FilenameUtils.getExtension(fileName);
			String largePath = uploadPath + uuid + "-large." + DEST_EXTENSION;
			String mediumPath = uploadPath + uuid + "-medium." + DEST_EXTENSION;
			String thumbnailPath = uploadPath + uuid + "-thumbnail." + DEST_EXTENSION;

			File tempFile = new File(System.getProperty("java.io.tmpdir") + "/upload_" + UUID.randomUUID() + ".tmp");
			if (!tempFile.getParentFile().exists()) {
				tempFile.getParentFile().mkdirs();
			}

			if (multipartFile != null && !multipartFile.isEmpty()) {
				multipartFile.transferTo(tempFile);
			} else if (isCollected) {
				tempFile = productImage.getFile();
			}

			addTask(sourcePath, largePath, mediumPath, thumbnailPath, tempFile, contentType);

			productImage.setSource(sourcePath);
			productImage.setLarge(largePath);
			productImage.setMedium(mediumPath);
			productImage.setThumbnail(thumbnailPath);
		} catch (Exception e) {
			logger.error("ProductImage构建错误：" + e);
		}
	}

}